package com.common.utils;

import java.io.IOException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ConnectionUtils {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionUtils.class);
	
	private static final Lock LOCK = new ReentrantLock();
	
	private static Connection conn = null;
	
	private ConnectionUtils() {
		super();
	}
	
	/**
	 * 获得新建或者缓存的hbase connection
	 * @return
	 */
	public static Connection getConn()
	{
		if (null != conn)
		{
			return conn;
		}
		
		LOCK.lock();
		try {
			if (null != conn)
			{
				return conn;
			}
			else
			{
				Configuration conf = HBaseConfiguration.create();
				conn = ConnectionFactory.createConnection(conf);
				return conn;
			}
		} catch (IOException e) {
			String exMsg = "create connection failed";
			LOGGER.error(exMsg, e);
			//这里throw了RuntimeException,可以确保方法不会报缺少返回值的错误
			throw new RuntimeException(exMsg, e);
		} finally {
			LOCK.unlock();
		}
	}
	
	/**
	 * 获得新建或者缓存的hbase connection
	 * @return
	 */
	public static Connection getConn(Configuration conf)
	{
		if (null != conn)
		{
			return conn;
		}
		
		LOCK.lock();
		try {
			if (null != conn)
			{
				return conn;
			}
			else
			{
				if (null == conf)
				{
					conf = HBaseConfiguration.create();
				}
				conn = ConnectionFactory.createConnection(conf);
				return conn;
			}
		} catch (IOException e) {
			String exMsg = "create connection failed";
			LOGGER.error(exMsg, e);
			//这里throw了RuntimeException,可以确保方法不会报缺少返回值的错误
			throw new RuntimeException(exMsg, e);
		} finally {
			LOCK.unlock();
		}
	}
	
	/**
	 * 必须/通常在应用关闭的时候调用，或者加一个shutdown的hook(但是这种方法"kill -9"应该不生效)
	 */
	public static void closeConn()
	{
		LOGGER.info("close htable connection={}", conn);
		
		if (null == conn)
		{
			return;
		}
		
		LOCK.lock();
		try {
			if (null == conn)
			{
				return;
			}
			IOUtils.closeStream(conn);
			conn = null;
		} finally
		{
			LOCK.unlock();
		}
	}
}
